import logging
from PIL import Image, ImageDraw, ImageFont
from pathlib import Path
import datetime
import csv
import os

logger = logging.getLogger(__name__)

class ImageProcessor:
    def __init__(self):
        self.font_size = 48  # 增大默认字体大小，从36改为48
        self.font_color = (255, 255, 255, 128)  # 半透明白色
        self.offset_y = 10  # 距离顶部的距离
        # 创建以日期时间命名的输出子目录
        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        self.output_dir = Path('output') / timestamp
        self.output_dir.mkdir(parents=True, exist_ok=True)
        logger.info(f"创建输出目录: {self.output_dir}")
        # 初始化ID映射字典 - 修改为存储完整的映射关系
        self.id_mapping = {}  # {身份证号: (报名序号, 准考证号)}
        # 初始化字体
        self._init_font()
        
    def _init_font(self):
        """初始化支持中文的字体"""
        # 尝试多个可能的中文字体路径
        font_paths = [
            # Windows 常用中文字体
            "c:/windows/fonts/simhei.ttf",  # 黑体
            "c:/windows/fonts/simsun.ttc",  # 宋体
            "c:/windows/fonts/simkai.ttf",  # 楷体
            "c:/windows/fonts/msyh.ttc",    # 微软雅黑
            "c:/windows/fonts/msyhbd.ttc",  # 微软雅黑粗体
            # 如果字体在资源目录中
            str(Path('resources') / "simhei.ttf"),
            # 同一目录下
            "simhei.ttf",
        ]
        
        self.font = None
        for font_path in font_paths:
            try:
                if os.path.exists(font_path):
                    self.font = ImageFont.truetype(font_path, self.font_size)
                    logger.info(f"成功加载字体: {font_path}")
                    return
            except Exception as e:
                logger.warning(f"加载字体失败 {font_path}: {e}")
                
        logger.warning("无法找到合适的中文字体，将使用默认字体")
        self.font = ImageFont.load_default()

    def load_id_mapping(self, csv_file_path: str) -> bool:
        """从CSV文件加载身份证号与准考证号的映射关系"""
        self.id_mapping = {}
        
        # 尝试多种可能的编码
        encodings = ['gbk', 'gb2312', 'gb18030', 'utf-8-sig', 'utf-8']
        
        for encoding in encodings:
            try:
                logger.info(f"尝试使用 {encoding} 编码读取CSV文件...")
                with open(csv_file_path, 'r', encoding=encoding) as file:
                    reader = csv.reader(file)
                    # 跳过标题行
                    next(reader, None)
                    for row in reader:
                        if len(row) >= 3:
                            registration_no = row[0].strip()  # 报名序号
                            exam_id = row[1].strip()          # 准考证号
                            identity_id = row[2].strip()      # 身份证号
                            # 存储完整映射关系
                            self.id_mapping[identity_id] = (registration_no, exam_id)
                
                logger.info(f"成功使用 {encoding} 编码加载ID映射: {len(self.id_mapping)}条记录")
                return True
            except UnicodeDecodeError:
                logger.warning(f"使用 {encoding} 编码读取CSV文件失败，尝试其他编码")
            except Exception as e:
                logger.error(f"读取CSV文件失败: {e}")
                
        logger.error("尝试了所有编码方式，均无法成功读取CSV文件")
        return False

    def add_watermark(self, input_path: str, output_path: str = None) -> bool:
        """添加水印到图片(单水印版本，保留向后兼容)"""
        try:
            # 始终使用output_dir中的路径
            input_path = Path(input_path)
            output_path = self.output_dir / f"{input_path.stem}_watermarked{input_path.suffix}"

            # 打开图片
            with Image.open(input_path) as img:
                # 创建一个可以在其上绘图的副本
                watermarked = img.copy()
                draw = ImageDraw.Draw(watermarked)
                
                # 获取文件名作为水印文字
                watermark_text = Path(input_path).stem
                
                # 使用初始化好的字体
                adaptive_font_size = min(48, int(watermarked.width / 15))  # 增大字体，从25改为15
                try:
                    font = ImageFont.truetype(self.font.path, adaptive_font_size)
                except:
                    font = self.font

                # 计算文字大小
                text_bbox = draw.textbbox((0, 0), watermark_text, font=font)
                text_width = text_bbox[2] - text_bbox[0]
                text_height = text_bbox[3] - text_bbox[1]

                # 计算文字位置（顶部居中）
                x = (watermarked.width - text_width) // 2  # 水平居中
                y = self.offset_y  # 靠近顶部

                # 绘制水印
                draw.text((x, y), watermark_text, font=font, fill=self.font_color)
                
                # 保存图片
                watermarked.save(output_path)
                logger.info(f"成功添加水印: {output_path}")
                return True

        except Exception as e:
            logger.error(f"处理图片失败 {input_path}: {str(e)}")
            return False
            
    def add_dual_watermarks(self, input_path: str, output_path: str = None) -> bool:
        """添加双水印到图片(身份证号和准考证号)"""
        try:
            # 始终使用output_dir中的路径
            input_path = Path(input_path)
            output_path = self.output_dir / f"{input_path.stem}_watermarked{input_path.suffix}"

            # 打开图片
            with Image.open(input_path) as img:
                # 创建一个可以在其上绘图的副本
                watermarked = img.copy()
                draw = ImageDraw.Draw(watermarked)
                
                # 获取文件名作为身份证号水印文字
                identity_id = Path(input_path).stem
                
                # 查找对应的准考证号
                exam_id = self.id_mapping.get(identity_id, "未找到对应准考证号")
                
                # 使用初始化好的中文字体，并根据图片大小调整字体大小
                adaptive_font_size = min(48, int(watermarked.width / 15))  # 增大字体，从25改为15
                try:
                    font = ImageFont.truetype(self.font.path, adaptive_font_size)
                except:
                    font = self.font

                # 添加身份证号水印（顶部）
                id_text = "身份证号 " + identity_id
                text_bbox = draw.textbbox((0, 0), id_text, font=font)
                text_width = text_bbox[2] - text_bbox[0]
                text_height = text_bbox[3] - text_bbox[1]
                x = (watermarked.width - text_width) // 2  # 水平居中
                y = self.offset_y  # 靠近顶部
                draw.text((x, y), id_text, font=font, fill=self.font_color)
                
                # 添加准考证号水印（在身份证号下方）
                exam_id_text = "准考证号 " + exam_id
                text_bbox2 = draw.textbbox((0, 0), exam_id_text, font=font)
                text_width2 = text_bbox2[2] - text_bbox2[0]
                x2 = (watermarked.width - text_width2) // 2  # 水平居中
                y2 = y + text_height + 5  # 在身份证号下方留点间隔
                draw.text((x2, y2), exam_id_text, font=font, fill=self.font_color)
                
                # 保存图片
                watermarked.save(output_path)
                logger.info(f"成功添加双水印: {output_path}")
                return True

        except Exception as e:
            logger.error(f"处理图片失败 {input_path}: {str(e)}")
            return False
            
    def add_triple_watermarks(self, input_path: str, output_path: str = None) -> bool:
        """添加三重水印到图片(身份证号、准考证号和报名序号)"""
        try:
            # 始终使用output_dir中的路径
            input_path = Path(input_path)
            output_path = self.output_dir / f"{input_path.stem}_watermarked{input_path.suffix}"

            # 打开图片
            with Image.open(input_path) as img:
                # 创建一个可以在其上绘图的副本
                watermarked = img.copy()
                draw = ImageDraw.Draw(watermarked)
                
                # 获取文件名作为身份证号水印文字
                identity_id = Path(input_path).stem
                
                # 查找对应的信息
                registration_no = "未找到对应报名序号"
                exam_id = "未找到对应准考证号"
                if identity_id in self.id_mapping:
                    registration_no, exam_id = self.id_mapping[identity_id]
                
                # 使用初始化好的中文字体，并根据图片大小调整字体大小
                adaptive_font_size = min(48, int(watermarked.width / 15))
                try:
                    font = ImageFont.truetype(self.font.path, adaptive_font_size)
                except:
                    font = self.font

                # 添加身份证号水印（顶部第一行）
                id_text = "身份证号 " + identity_id
                text_bbox = draw.textbbox((0, 0), id_text, font=font)
                text_width = text_bbox[2] - text_bbox[0]
                text_height = text_bbox[3] - text_bbox[1]
                x = (watermarked.width - text_width) // 2  # 水平居中
                y = self.offset_y  # 靠近顶部
                draw.text((x, y), id_text, font=font, fill=self.font_color)
                
                # 添加准考证号水印（第二行）
                exam_id_text = "准考证号 " + exam_id
                text_bbox2 = draw.textbbox((0, 0), exam_id_text, font=font)
                text_width2 = text_bbox2[2] - text_bbox2[0]
                x2 = (watermarked.width - text_width2) // 2  # 水平居中
                y2 = y + text_height + 5  # 在身份证号下方留点间隔
                draw.text((x2, y2), exam_id_text, font=font, fill=self.font_color)
                
                # 添加报名序号水印（第三行）
                reg_text = "报名序号 " + registration_no
                text_bbox3 = draw.textbbox((0, 0), reg_text, font=font)
                text_width3 = text_bbox3[2] - text_bbox3[0]
                x3 = (watermarked.width - text_width3) // 2  # 水平居中
                y3 = y2 + text_height + 5  # 在准考证号下方留点间隔
                draw.text((x3, y3), reg_text, font=font, fill=self.font_color)
                
                # 保存图片
                watermarked.save(output_path)
                logger.info(f"成功添加三重水印: {output_path}")
                return True

        except Exception as e:
            logger.error(f"处理图片失败 {input_path}: {str(e)}")
            return False
            
    def process_images_with_dual_watermarks(self, image_paths: list, csv_file_path: str) -> tuple:
        """批量处理图片，添加双水印"""
        if not self.load_id_mapping(csv_file_path):
            return 0, 0
            
        success_count = 0
        error_count = 0
        
        for image_path in image_paths:
            if self.add_dual_watermarks(image_path):
                success_count += 1
            else:
                error_count += 1
                
        return success_count, error_count

    def process_images_with_triple_watermarks(self, image_paths: list, csv_file_path: str) -> tuple:
        """批量处理图片，添加三重水印"""
        if not self.load_id_mapping(csv_file_path):
            return 0, 0
            
        success_count = 0
        error_count = 0
        
        for image_path in image_paths:
            if self.add_triple_watermarks(image_path):
                success_count += 1
            else:
                error_count += 1
                
        return success_count, error_count
